#pragma once
#include <functional>

#include "RenderGraphBuilder.h"
#include "RendererInterface.h"
#include "Scene.h"
#include "Runtime/Thread/Task.h"
#include "Runtime/Engine/SceneView.h"
#include "Runtime/Engine/SceneVisibility.h"
#include "Runtime/Thread/Event.h"

namespace Alice
{
    /** The renderer module implementation. */
    class RendererModule final : public IRendererModule
    {
    public:
        std::unordered_set<SceneInterface*> mAllocatedScenes;
        RendererModule();
        void BeginRenderingViewFamily(SceneViewFamily* inSceneViewFamily);
    };
    class ViewInfo:public SceneView
    {
    public:
        /** A map from primitive ID to a boolean visibility value. */
        std::vector<bool> mPrimitiveVisibilityMap;
    };
    /**
     * View family plus associated transient scene textures.
     */
    class ViewFamilyInfo : public SceneViewFamily
    {
    public:
        SceneInterface* Scene = nullptr;
        ViewFamilyInfo(const SceneViewFamily& InViewFamily);
    };
    struct FUpdateParameters
    {
        std::function<void(const TaskHandle*)> mPostStaticMeshUpdate;
    };
    /**
     * Used as the scope for scene rendering functions.
     * It is initialized in the game thread by FSceneViewFamily::BeginRender, and then passed to the rendering thread.
     * The rendering thread calls Render(), and deletes the scene renderer when it returns.
     */
    class SceneRenderer
    {
    public:
        Scene* Scene = nullptr;
        ViewFamilyInfo mViewFamilyInfo;
        std::vector<ViewInfo*> mViews;
        std::vector<ViewInfo*> mAllViews;
        SceneRenderer(const SceneViewFamily*inSceneViewFamily);
        virtual void Render(RDGBuilder& GraphBuilder) = 0;
        IVisibilityTaskData* OnRenderBegin(RDGBuilder& GraphBuilder);
        void SetupMeshPass(ViewInfo& inViewInfo,
           //FExclusiveDepthStencil::Type BasePassDepthStencilAccess,
            FViewCommands& ViewCommands
            //FInstanceCullingManager& InstanceCullingManager
            );
    };
    class DeferredShadingRenderer:public SceneRenderer
    {
    public:
        DeferredShadingRenderer(const SceneViewFamily*inSceneViewFamily);
        void Render(RDGBuilder& GraphBuilder);
        /** Determines which primitives are visible for each view. */
        void BeginInitViews(
            RDGBuilder& GraphBuilder,FInitViewTaskDatas&inVisibilityTaskData);
        void EndInitViews(
            RDGBuilder& GraphBuilder,FInitViewTaskDatas&inVisibilityTaskData);
    };
}
